package com.jz.community.basecomm.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created by Tony.Fan on 2018/3/15 10:07
 * 模块反射通用方法
 */
public class ModuleReflectUtils {
    /**
     * 不需要返回值的方法
     *
     * @param className      类名
     * @param methodName     方法名
     * @param classes        所有的参数类型  例:new Class[]{int.class,Stirng.class}
     * @param params         所有的具体参数  例:new Object[]{type,name}
     * @param isStaticMethod 是否是静态方法
     */
    public static void notReturnMethod(String className, String methodName, Class[] classes, Object[] params, boolean isStaticMethod) {
        handleIsReturn(className, methodName, classes, params, isStaticMethod);
    }

    /**
     * 處理是否返回
     *
     * @param className
     * @param methodName
     * @param classes
     * @param params
     * @param isStaticMethod
     */
    private static Object handleIsReturn(String className, String methodName, Class[] classes, Object[] params, boolean isStaticMethod) {
        Class classObj = getClass(className);
        if (classObj != null) {
            try {
                Method method = null;
                if (classes != null) {
                    method = handleMethodParamsType(methodName, classes, classObj, method);
                } else {
                    method = classObj.getMethod(methodName);
                }
                if (method != null) {
                    return handleMethodActualParams(params, classObj, method, isStaticMethod);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 需要返回值的方法
     *
     * @param className
     * @param methodName
     * @param classes
     * @param params
     */
    public static Object returnMethod(String className, String methodName, Class[] classes, Object[] params, boolean isStaticMethod) {
        return handleIsReturn(className, methodName, classes, params, isStaticMethod);
    }

    /**
     * 处理参数类型的调用
     *
     * @param methodName
     * @param classes
     * @param classObj
     * @param method
     * @return
     * @throws NoSuchMethodException
     */
    private static Method handleMethodParamsType(String methodName, Class[] classes, Class classObj, Method method)
            throws NoSuchMethodException {
        switch (classes.length) {
            case 1:
                method = classObj.getMethod(methodName, classes[0]);
                break;
            case 2:
                method = classObj.getMethod(methodName, classes[0], classes[1]);
                break;
            case 3:
                method = classObj.getMethod(methodName, classes[0], classes[1], classes[2]);
                break;
            case 4:
                method = classObj.getMethod(methodName, classes[0], classes[1], classes[2], classes[3]);
                break;
            case 5:
                method = classObj.getMethod(methodName, classes[0], classes[1], classes[2], classes[3], classes[4]);
                break;

        }
        if (classes.length > 5) {
            throw new RuntimeException("暂不支持6个或6个以上参数调用");
        }
        return method;
    }

    /**
     * 处理方法实际参数的调用
     *
     * @param params
     * @param classObj
     * @param method
     * @param isStaticMethod
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    private static Object handleMethodActualParams(Object[] params, Class classObj, Method method, boolean isStaticMethod)
            throws IllegalAccessException, InvocationTargetException, InstantiationException {
        if (params != null) {

            if (params.length > 5) {
                throw new RuntimeException("暂不支持6个或6个以上参数调用");
            }

            if (isStaticMethod) {
                switch (params.length) {
                    case 1:
                        return method.invoke(classObj, params[0]);
                    case 2:
                        return method.invoke(classObj, params[0], params[1]);
                    case 3:
                        return method.invoke(classObj, params[0], params[1], params[2]);

                    case 4:
                        return method.invoke(classObj, params[0], params[1], params[2], params[3]);

                    case 5:
                        return method.invoke(classObj, params[0], params[1], params[2], params[3], params[4]);
                }
            } else {
                switch (params.length) {
                    case 1:
                        return method.invoke(classObj.newInstance(), params[0]);
                    case 2:
                        return method.invoke(classObj.newInstance(), params[0], params[1]);
                    case 3:
                        return method.invoke(classObj.newInstance(), params[0], params[1], params[2]);

                    case 4:
                        return method.invoke(classObj.newInstance(), params[0], params[1], params[2], params[3]);

                    case 5:
                        return method.invoke(classObj.newInstance(), params[0], params[1], params[2], params[3], params[4]);
                }
            }
        } else {
            return method.invoke(classObj.newInstance());
        }
        return null;
    }

    /**
     * 获取登录注册的对外公开方法对象
     *
     * @return
     */
    private static Class getClass(String className) {
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }
}
